package com.yu.yupicturebackend.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yu.yupicturebackend.exception.BusinessException;
import com.yu.yupicturebackend.exception.ErrorCode;
import com.yu.yupicturebackend.exception.ThrowUtils;
import com.yu.yupicturebackend.mapper.SpaceMapper;
import com.yu.yupicturebackend.model.dto.space.analyze.*;
import com.yu.yupicturebackend.model.entity.Picture;
import com.yu.yupicturebackend.model.entity.Space;
import com.yu.yupicturebackend.model.entity.User;
import com.yu.yupicturebackend.model.vo.space.analyze.*;
import com.yu.yupicturebackend.service.PictureService;
import com.yu.yupicturebackend.service.SpaceAnalyzeService;
import com.yu.yupicturebackend.service.SpaceService;
import com.yu.yupicturebackend.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author zy
* @description 针对表【space(空间)】的数据库操作Service实现
* @createDate 2025-03-04 10:47:21
*/
@Service

public class SpaceAnalyzeServiceImpl extends ServiceImpl<SpaceMapper, Space>
    implements SpaceAnalyzeService {

    @Resource
    private UserService userService;
    @Resource
    private SpaceService spaceService;
    @Resource
    private PictureService pictureService;

    /**
     * 获取空间使用情况分析
     * @param spaceUsageAnalyzeRequest
     * @param login
     * @return
     */
    @Override
    public SpaceUsageAnalyzeResponse getSpaceUsageAnalyze(SpaceUsageAnalyzeRequest spaceUsageAnalyzeRequest, User login) {
        // 校验参数
        // 全空间或公共图库，需要从picture 表中查询
        if (spaceUsageAnalyzeRequest.isQueryAll() || spaceUsageAnalyzeRequest.isQueryPublic()){
            // 校验权限、仅管理员可以使用访问
            checkSpaceAnalyze(spaceUsageAnalyzeRequest,login);
            // 统计图库的使用空间
            QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("picSize");
            // 补充查询范围
            fillAnalyzeQueryWrapper(spaceUsageAnalyzeRequest,queryWrapper);
            List<Object> pictureObjList = pictureService.getBaseMapper().selectObjs(queryWrapper);
            long usedSize = pictureObjList.stream().mapToLong(obj -> (Long) obj).sum();
            long usedCount = pictureObjList.size();
            // 封装返回结果
            SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
            spaceUsageAnalyzeResponse.setUsedSize(usedSize);
            spaceUsageAnalyzeResponse.setUsedCount(usedCount);
            // 公共图库无上限、无比例
            spaceUsageAnalyzeResponse.setMaxSize(null);
            spaceUsageAnalyzeResponse.setSizeUsageRatio(null);
            spaceUsageAnalyzeResponse.setMaxCount(null);
            spaceUsageAnalyzeResponse.setCountUsageRatio(null);

            return spaceUsageAnalyzeResponse;
        } else {
            // 私有空间，需要从space 表中查询
            Long spaceId = spaceUsageAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(spaceId==null,ErrorCode.PARAMS_ERROR,"空间id不能为空");
            // 校验空间信息
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space==null,ErrorCode.NOT_FOUND_ERROR,"空间不存在");
            // 校验权限、仅管理员可以使用访问
            checkSpaceAnalyze(spaceUsageAnalyzeRequest,login);
            // 封装返回结果
            SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
            spaceUsageAnalyzeResponse.setUsedSize(space.getTotalSize());
            spaceUsageAnalyzeResponse.setMaxSize(space.getMaxSize());
            spaceUsageAnalyzeResponse.setUsedCount(space.getTotalCount());
            spaceUsageAnalyzeResponse.setMaxCount(space.getMaxCount());
            // 计算使用率
            double sizeUsageRatio = NumberUtil.round(space.getTotalSize()*100.0/space.getMaxSize(),2).doubleValue();
            double countUsageRatio = NumberUtil.round(space.getTotalCount()*100.0/space.getMaxCount(),2).doubleValue();
            spaceUsageAnalyzeResponse.setSizeUsageRatio(sizeUsageRatio);
            spaceUsageAnalyzeResponse.setCountUsageRatio(countUsageRatio);
            return spaceUsageAnalyzeResponse;
        }
    }

    /**
     * 获取空间分类分析
     * @param spaceCategoryAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest spaceCategoryAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceCategoryAnalyzeRequest==null,ErrorCode.PARAMS_ERROR,"请求参数不能为空");
        // 校验权限
        checkSpaceAnalyze(spaceCategoryAnalyzeRequest,loginUser);

        // 改造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceCategoryAnalyzeRequest,queryWrapper);

        // 使用 MybatisPlus 分组查询
        queryWrapper.select("category","count(*) as count","sum(picSize) as totalSize")
                .groupBy("category");

        // 查询结果
        return pictureService.getBaseMapper().selectMaps(queryWrapper)
                .stream()
                .map(result ->{
                    String category = result.get("category")!=null?(String) result.get("category"):"未分类";
                    Long count = ((Number) result.get("count")).longValue();
                    Long totalSize = ((Number) result.get("totalSize")).longValue();
                    return new SpaceCategoryAnalyzeResponse(category,count,totalSize);
                })
                .collect(Collectors.toList());
    }

    /**
     * 获取空间标签分析
     * @param spaceTagAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceTagAnalyzeResponse> getSpaceTagAnalyze(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceTagAnalyzeRequest==null,ErrorCode.PARAMS_ERROR,"请求参数不能为空");
        // 校验权限
        checkSpaceAnalyze(spaceTagAnalyzeRequest,loginUser);

        // 改造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceTagAnalyzeRequest,queryWrapper);

        // 查询符号条件的标签
        queryWrapper.select("tags");
        List<String> tagsObjList = pictureService.getBaseMapper().selectObjs(queryWrapper)
                .stream()
                .filter(ObjUtil::isNotNull)
                .map(Object::toString)
                .collect(Collectors.toList());

        // 解析标签并统计
        Map<String,Long> tagCountMap = tagsObjList.stream()
                //["java", "python"],[ "python"]=>"java","python","python"
                .flatMap(tagsJson-> JSONUtil.toList(tagsJson,String.class).stream())
                .collect(Collectors.groupingBy(tag->tag,Collectors.counting()));

        // 装换为响应对象，按照使用次数进行排序
        return tagCountMap.entrySet().stream()
                .sorted((e1,e2)->Long.compare(e2.getValue(), e1.getValue()))// 降序排序
                .map(entry->new SpaceTagAnalyzeResponse(entry.getKey(),entry.getValue()))
                .collect(Collectors.toList());
    }

    /**
     * 获取空间大小分析
     * @param spaceSizeAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyze(SpaceSizeAnalyzeRequest spaceSizeAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceSizeAnalyzeRequest==null,ErrorCode.PARAMS_ERROR,"请求参数不能为空");
        // 校验权限
        checkSpaceAnalyze(spaceSizeAnalyzeRequest,loginUser);

        // 改造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceSizeAnalyzeRequest,queryWrapper);

        // 查询所有符号条件的图片大小
        // 100/ 200/ 300
        // 从pictureService的BaseMapper中获取图片大小列表
        // 使用Stream API对获取到的对象流进行处理
        // 过滤掉空值，确保只处理非空的图片大小
        // 将过滤后的对象转换为Long类型，统一数据类型
        // 最后收集转换后的数据，生成一个包含所有非空图片大小的List
        // 查询所有符合条件的图片大小
        queryWrapper.select("picSize");
        List<Long> picSizeList = pictureService.getBaseMapper().selectObjs(queryWrapper)
                .stream()
                .filter(ObjUtil::isNotNull)
                .map(picSize->(Long)picSize)
                .collect(Collectors.toList());

        // 定义分段范围，注意使用有序的map
        Map<String,Long> sizeRangeMap = new LinkedHashMap<>();
        sizeRangeMap.put("<100KB",picSizeList.stream().filter(picSize-> picSize <100*1024).count());
        sizeRangeMap.put("100KB-500KB",picSizeList.stream().filter(picSize-> picSize >=100*1024 && picSize <500*1024).count());
        sizeRangeMap.put("500KB-1MB",picSizeList.stream().filter(picSize-> picSize >=500*1024 && picSize <1024*1024).count());
        sizeRangeMap.put(">1MB",picSizeList.stream().filter(picSize->picSize>=1024*1024).count());

        // 将分段范围转换为响应对象
        return sizeRangeMap.entrySet().stream()
                .map(entry ->new SpaceSizeAnalyzeResponse(entry.getKey(),entry.getValue()))
                .collect(Collectors.toList());
    }

    /**
     * 获取空间用户分析
     * @param spaceUserAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalyzeRequest spaceUserAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceUserAnalyzeRequest==null,ErrorCode.PARAMS_ERROR,"请求参数不能为空");
        // 校验权限
        checkSpaceAnalyze(spaceUserAnalyzeRequest,loginUser);

        // 改造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceUserAnalyzeRequest,queryWrapper);
        // 补充查询条件，查询所有符合要求的用户id
        Long userId = spaceUserAnalyzeRequest.getUserId();
        queryWrapper.eq(ObjUtil.isNotNull(userId),"userId",userId);
        // 补充分析维度:每日，每周，每月
        String timeDimension = spaceUserAnalyzeRequest.getTimeDimension();
        switch (timeDimension){
            case "day":
                queryWrapper.select("DATE_FORMAT(createTime,'%Y-%m-%d') as period","count(*) as count");
                break;
            case "week":
                queryWrapper.select("YEARWEEK(createTime) as period","count(*) as count");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(createTime,'%Y-%m') as period","count(*) as count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"时间维度错误");
        }

        // 分组排序
        queryWrapper.groupBy("period").orderByAsc("period");

        // 查询结果封装结果
        List<Map<String,Object>> queryResult = pictureService.getBaseMapper().selectMaps(queryWrapper);
        return queryResult.stream()
                .map(result->{
                    String period = result.get("period").toString();
                    Long count = ((Number) result.get("count")).longValue();
                    return new SpaceUserAnalyzeResponse(period,count);
                })
                .collect(Collectors.toList());

    }

    /**
     * 获取空间排名分析(仅管理员)
     * @param spaceRankAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceRankAnalyzeRequest==null,ErrorCode.PARAMS_ERROR,"请求参数不能为空");

        // 校验权限, 仅管理员可访问
        ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);

        // 改造查询条件
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id","spaceName","userId","totalSize")
                .orderByDesc("totalSize")
                .last("limit "+spaceRankAnalyzeRequest.getTopN());

        // 查询结果封装结果
        return spaceService.getBaseMapper().selectList(queryWrapper);
    }


    /**
     * 校验空间分析权限
     * @param spaceAnalyzeRequest
     * @param loginUser
     */
    public void checkSpaceAnalyze(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();
         // 全空间分析或者公共图库权限校验：仅管理员可访问
        if (queryAll || queryPublic){
            ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR,"无权限访问公共空间");
        } else {
            // 私有空间分析权限校验：仅管理员或本人可访问
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(spaceId==null,ErrorCode.PARAMS_ERROR,"空间id不能为空");
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space==null,ErrorCode.NOT_FOUND_ERROR,"空间不存在");
            spaceService.checkSpaceAuth(loginUser,space);
        }
    }


    /**
     * 根据请求参数，填充查询条件
     * @param spaceAnalyzeRequest
     * @param queryWrapper
     */
    public void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper){
        // 全空间分析
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();
        if (queryAll){
            return;
        }
        // 公共图库分析
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        if (queryPublic){
            queryWrapper.isNull("spaceId");
            return;
        }
        // 私有图库分析
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        if (spaceId!=null){
            queryWrapper.eq("spaceId",spaceId);
            return;
        }
        throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"未指定查询范围");

    }
}




